﻿using System;
using System.IO;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using KnowledgeKiosk.Parsers;

namespace KnowledgeKiosk.FeedUpdaters
{
    /// <summary>
    /// Provides a way to periodically load and deserialize items from a web-based XML data source
    /// </summary>
    /// <typeparam name="T">Specifies the type of objects that will be retrieved.</typeparam>
    public class WebClientFeedUpdater<T> : AbstractXmlFeedUpdater<T>
    {
        /// <summary>
        /// Initializes a new instance of the WebClientFeedUpdater(Of T) class using the specified
        /// feed Uri, Xml-to-Object parser and update interval.
        /// </summary>
        /// <param name="feedUri">Uri of the web-based XML data source</param>
        /// <param name="xmlParser">Parser that translates XML to strongly typed objects.</param>
        /// <param name="updateInterval">Interval of the update cycle.</param>
        public WebClientFeedUpdater(Uri feedUri, IXmlToObjectParser<T> xmlParser, TimeSpan updateInterval)
            : base(feedUri, xmlParser, updateInterval)
        {
        }

        /// <summary>
        /// Called when the update interval has elapsed.
        /// </summary>
        internal override void Tick(object sender, EventArgs e)
        {
            var client = new WebClient();
            client.DownloadStringCompleted += DownloadStringCompleted;
            client.DownloadStringAsync(FeedUri);
        }

        /// <summary>
        /// Called when the web-based source has returned a response.
        /// </summary>
        /// <param name="sender">The control that raised the event.</param>
        /// <param name="e">The contents of the response.</param>
        private void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            try
            {
                if (IsJson(e.Result))
                {
                    using (var xr = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(e.Result), XmlDictionaryReaderQuotas.Max))
                    {
                        XElement xml = XElement.Load(xr, LoadOptions.PreserveWhitespace);
                        ParseXmlData(xml);
                    }
                }
                else
                {
                    using (var sr = new StringReader(e.Result))
                    {
                        using (XmlReader xr = XmlReader.Create(sr))
                        {
                            XElement xml = XElement.Load(xr, LoadOptions.PreserveWhitespace);
                            ParseXmlData(xml);
                        }
                    }
                }
                if (RetryEnabled && IsRetrying)
                    ResetRetryInterval();
            }
            catch(Exception ex)
            {
                Logger.WriteLine(ex);

                SetRetryInterval();
            }
        }

        private static bool IsJson(string input)
        {
            input = input.Trim();
            return input.StartsWith("{") && input.EndsWith("}")
                   || input.StartsWith("[") && input.EndsWith("]");
        }
    }
}